﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include "vld.h"
//int main()
//{
//	int* p = (int*)malloc(5 * sizeof(int));
//	int** arr = (int**)malloc(3*sizeof(int*));
//
//}

//int main()
//{
//	FILE* pf = fopen("data.txt", "r");
//	if (pf == NULL)
//	{
//		perror("fopen read Error");
//		return 1;
//	}
//
//	FILE* pw = fopen("data_copy.txt", "w");//"w"，指定文件不存在就就创建指定文件
//	if (pw == NULL)
//	{
//		perror("fopen write Error");
//		return 1;
//	}
//
//	//边读边写
//	int ch = 0;
//	while ((ch = fgetc(pf)) != EOF)//EOF文件结束符。文本文件中，EOF作为文件结束符，碰到文件结束符，ch的值为EOF，即-1
//	{
//		fputc(ch, pw);
//	}
//	fclose(pf);
//	fclose(pw);
//	pf = NULL;
//	pw = NULL;	
//	return 0;
//}



//写一个程序来拷贝文件
//void CopyTxt()
//{
//	FILE* pf = fopen("data.txt", "r");
//	if (pf == NULL)
//	{
//		perror("fopen read Error");
//		return 1;
//	}
//	FILE* pw = fopen("data_copy.txt", "w");
//	if (pw == NULL)
//	{
//		perror("fopen write Error");
//		return 1;
//	}
//
//	//开始一边读 一边写，拷贝的功能
//	int ch = 0;
//	while ((ch = fgetc(pf)) != EOF)
//	{
//		fputc(ch, pw);
//	}
//	fclose(pf);
//	fclose(pw);
//	pf = NULL;
//	pw = NULL;
//}
//
//int main()
//{
//	CopyTxt();
//	return 0;
//}


//统计字符的个数
//int main()
//{
//	long num = 0;
//	FILE* pf = NULL;
//	if ((pf = fopen("fname.dat","r")) == NULL)
//	{
//		printf("Can't open the file!");
//		exit(0);
//	}
//	while (fgetc(pf) != EOF)
//	{
//		num++;
//	}
//	printf("num = %d\n", num);
//	fclose(pf);
//	return 0;
//}


//C语言中关于文件读写函数说法：
//1.fgetc是适用于所有输入流字符输入函数
//2.fputs是适用于所有输出流的文件行输出函数
//3.fread是适用于文件输入流的二进制输入函数


//文件名的说法
//文件名中有一些禁止使用的字符
//文件名中不一定包含后缀名
//文件的后缀名决定了一个文件的默认打开方式
//文件路径指的是从盘符到该文件所经历的路径中各符号名的集合

//fopen函数
//fopen打开文件的方式是"r",如果文件不存在，则打开文件失败
//fopen打印文件的方式是"w",如果文件不存在，则创建文件，打开成功
//fopen打开的文件需要fclose来关闭

//C语言以二进制方式打开一个文件的方法是：FILE *f = fopen("test.bin","wb");

//文本文件和二进制描述
//文本文件是可以读懂的，二进制文件没办法直接读懂
//数据在内存中以二进制的形式存储的，如果不加转换的输出到外存，就是二进制文件
//将内存中的数据转化成ASCII码值的形式，并以ASCII码值的形式存储的文件就是文本文件


//使用动态内存函数malloc函数模拟开辟一个3*5的整型二维数组，
//开辟好后，使用二维数组下标进行访问

int main()
{
	int* p = (int*)malloc(5 * sizeof(int));
	int** arr = (int**)malloc(3 * sizeof(int*));

	for (int i = 0; i < 3; i++)
	{
		arr[i] = (int*)malloc(5 * sizeof(int));
	}

	//进行赋值
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			arr[i][j] = 1;
		}
	}
	//打印
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}

	//释放动态申请的内存
	for (int i = 0; i < 3; i++)
	{
		free(arr[i]);
		arr[i] = NULL;
	}
	free(arr);
	arr = NULL;
	free(p);
	p = NULL;

	return 0;
}

//int main()
//{
//	int* p = (int*)malloc(5 * sizeof(int));
//	int** arr = (int**)malloc(3 * (sizeof(int*)));
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		arr[i] = (int*)malloc(5 * sizeof(int));
//	}
//	//进行赋值
//	for (i = 0; i < 3; i++)
//	{
//		for (int j = 0; j < 5; j++)
//		{
//			arr[i][j] = i+j;
//
//		}
//	}
//	//打印
//	for (int i = 0; i < 3; i++)
//	{
//		for (int j = 0; j < 5; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//	free(arr);
//  arr = NULL;
//	return 0;
//}


//数组串联
//nums:当前数组  numsSize:当前数组的长度 returnSize:返回的数组的长度
//int* getConcatenation(int* nums, int numsSize, int* returnSize)
//{
//	int* ans = (int*)malloc(sizeof(int) * numsSize * 2);
//	for (int i = 0; i < numsSize; i++)
//	{
//		ans[i] = nums[i];
//		ans[i + numsSize] = nums[i];
//	}
//	*returnSize = 2 * numsSize;
//	return ans;
//}
//
//int main()
//{
//	int arr[] = { 1,2,3 };
//	int returnSize = 0;
//	int* p = getConcatenation(arr, sizeof(arr) / sizeof(arr[0]), &returnSize);
//	for (int i = 0; i < returnSize; i++)
//	{
//		printf("%d ", *(p + i));
//	}
//	return 0;
//}


//char* GetMemory(void)
//{
//	char p[] = "hello world";
//	return p;//p数组是局部变量，当函数运行结束之后，程序会回收内存
//}
//
//void Test()
//{
//	char* str = NULL;
//	str = GetMemory();//GetMemory函数返回的地址无法正常使用
//	printf(str);//不一定可以打印
//}

//动态内存的错误有：1.对非动态内存的free释放；2.对动态内存的多次释放；3.对动态内存的越界访问
//free参数可以NULL。

//动态内存函数：
//1.malloc函数向内存申请一块连续的空间，并返回起始地址
//2.malloc申请空间失败，返回NULL指针
//3.malloc可以向内存申请0字节的空间
//4.malloc函数和calloc函数的功能都是相似的，都是申请一块连续的空间
//5.malloc函数申请的空间不初始化，calloc函数申请的空间会初始化为0
//6.realloc函数可以调整动态申请内存的大小，可大可小
//7.动态内存存储在堆区

//关于枚举常量和#define定义常量说法严谨的有：
//1.可读性更好：枚举符合提供了有意义的标记符，可以更清晰地表达代码的意图。
//相比之下,#define定义的符号只是简单的文本替换，不具备语义上大端含义。
//2.和#defined定义的标记符比较枚举有类型检查，更加严谨。
//3.枚举常量是遵循作用域规则的，会在整个代码中进行文本替换。


//序列中删除指定数字
//数据范围：序列长度和序列中的值都满足1≤n≤50
//输入描述：
//

//int main()
//{
//	int n; 
//	scanf("%d", &n);
//	int arr[50] = { 0 };
//	int i = 0;
//	for (i = 0; i < n; i++)
//	{
//		scanf("%d", &arr[i]);
//	}
//
//	int del = 0;
//	scanf("%d", &del);
//	int j = 0;
//	i = 0;
//	for (i = 0; i < n; i++)
//	{
//		if (arr[i] != del)
//		{
//			arr[j] = arr[i];
//			j++;
//		}
//	}
//	for (int k = 0; k < j; k++)
//	{
//		printf("%d ", arr[k]);
//	}
//	return 0;
//}




//变种水仙花数
//把任意的数字，从中间拆分成两个数字，比如1461可以拆成（1和461）,(14和61)，（146和1），
//如果所有拆分后的乘积之和等于自身，则是一个Lily Number.
////问题：求出5位数中的所有Lily Number
//int main()
//{
//	int i = 0;
//	for (i = 10000; i <= 99999; i++)
//	{
//		int j = 10;
//		int sum = 0;
//		for (j = 10; j <= 10000; j *= 10)
//		{
//			sum += (i / j) * (i % j);
//		}
//		if (sum == i)
//		{
//			printf("%d ", i);
//		}
//	}
//	return 0;
//}

//int main()
//{
//	union
//	{
//		short k;
//		char i[2];
//	}*s, a;
//	s = &a;
//	s->i[0] = 0x39;
//	s->i[1] = 0x38;
//	printf("%x\n", a.k);//3839
//	//小端：低地址存地数据
//	//0x11223344 -> 44 33 22 11
//	//			低地址		高地址
//
//	//0    0x39;  低
//	//1    0x38;  高⬆
//	return 0;
//}


#if 0
union Un
{
	short s[7];// 2 8 2
	int n;// 4 8 4
};

int main()
{
	printf("%d\n", sizeof(union Un));
	return 0;
}


int main()
{
	unsigned char puc[4];
	struct tagPIM
	{
		unsigned char ucPiml;
		unsigned char ucData0 : 1;
		unsigned char ucData1 : 2;
		unsigned char ucData2 : 3;
	}*pstPimData;
	pstPimData = (struct tagPIM*)puc;
	memset(puc, 0, 4);
	pstPimData->ucPiml = 2;
	pstPimData->ucData0 = 3;
	pstPimData->ucData1 = 4;
	pstPimData->ucData2 = 5;
	printf("%02x %02x %02x %02x\n", puc[0], puc[1], puc[2], puc[3]);
	//00000010   00101001   00000000   00000000   //数据从后往前存放
	//02           29           00        00  //注意这里是以16进制输出
	return 0;
}

#define MAX_SIZE 2+3
struct _Record_Struct
{
	unsigned char Env_Alarm_ID : 4;
	unsigned char Paral : 2;
	//上面这两个 共6个比特位 占1个字节
	unsigned char state;
	//上面这一个 本身占用1个字节
	unsigned char avail : 1;
	//上面这个 本身占用1个字节（1个bit位）
}*Env_Alarm_Record;//8个比特位


int main()
{
	struct _Record_Struct* pointer = (struct _Record_Struct*)malloc(sizeof(struct _Record_Struct) * 2 + 3);
																//3 * 2 + 3
	return 0;
}

typedef struct
{
	int a;//4 8 4
	char b;//1 8 1
	short c;//2 8 2
	short d;//2 8 2
}AA_t;


//32位机器下，默认对齐数4
struct A
{
	int a;//4 4 4
	short b;//2 4 2
	int c;//4 4 4
	char  d;//1 4 1
};//16

struct B
{
	int a;//4 4 4
	short b;//2 4 2
	char c;//1 4 1
	int d;//4 4 4
};//12f

int main()
{
	//printf("%d\n", sizeof(AA_t));//12
	printf("%d\n", sizeof(struct A));
	return 0;
}


/*atoi（）函数原型
int atoi(const char* str);
如果开始遇到了空格，那么需要一直过滤。
+ - 会影响这个数字的正负
在这个字符串当中当中，如果出现了非数字字符，那么就结束转换
如果 转换之后的数字 大于 int最大值，那么按照最大值算，相反，如果比最小值还小，那么就按照最小值算
 */

enum State
{
	VAILD,//不非法
	INVILD//非法
}state = INVILD;//

int MyAtoi(const char* str)
{
	assert(str != NULL);
	//如果传入空字符串返回0
	if (*str == '\0')
	{
		return 0;
	}

	//isspance 返回值不为0 ，代表是空格
	while (isspace(*str))
	{
		str++;
	}
	//代码走到这里之后str遇到的一定不是空格了
	int flag = 1;
	if (*str == '+')
	{
		flag = 1;
		str++;
	}
	else if(*str == '-')
	{
		flag = -1;
		str++;
	}

	//判断接下来的字符是否是数字
	//需要把字符串当中，所有的字符，全部判断一遍
	long long ret = 0;
	while (*str != '\0')
	{
		//返回值是不为0的
		if (isdigit(*str))
		{
			//是数字字符，把字符1变成数字1 -> '1' - '0' = 1 
			ret = ret * 10 + (*str - '0') * flag;
			if (ret > INT_MAX)
			{
				ret = INT_MAX;
			}
			if (ret < INT_MIN)
			{
				ret = INT_MIN;
			}
		}
		else
		{
			return (int)ret;
		}
		str++;
	}

	if (*str == '\0')
	{
		state = VAILD;
	}
	return (int)ret;
}

int main()
{
	int ret = MyAtoi("-123abc123");
	if (state == VAILD)
	{
		printf("合法转化：：%d\n", ret);
	}
	else
	{
		printf("不合法转化 ：%d\n",ret);
	}
	return 0;
}

struct S
{
	int a;
	int b;
};
int main()
{
	struct S a, * p = &a;
	a.a = 99;
	//printf("%d\n", *p.a);//err,  点'.'的优先级更高，这里会被解析为（p.a）;
	//正确写法如下
	printf("%d\n", (*p).a);//与下面这个表达式是等价的
	printf("%d\n",p->a );//~等价
	printf("%d\n",a.a);
	return 0;
}
#endif